home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_316 / life / life.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  506 lines

  1. /*
  2.  *   What fun!  A new LIFE program by Tomas Rokicki.  Commented rather
  3.  *   erratically; hell, this is all just one big hack.
  4.  */
  5. int modulo ;
  6. int wmodulo ;
  7. int vsize ;
  8. long msize ;
  9. #define RASTSIZE (wmodulo * (long)(vsize+1))
  10. #include "structures.h"
  11. #include "blit.h"
  12. short *a, *b, *c, *d, *e, *f, *t1=NULL, *t2=NULL, *t3=NULL, *t4=NULL ;
  13. short noplanes ;
  14. short torus ;
  15. short orify ;
  16. short asm ;
  17. struct GfxBase *GfxBase = NULL ;     /* the GfxBase */
  18. struct IntuitionBase *IntuitionBase = NULL ; /* the IntuitionBase */
  19. struct Screen *myscreen = NULL ;
  20. struct Window *mywindow = NULL ;
  21. struct TextAttr myfont = {(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0 };
  22. struct NewScreen mynewscreen = {0, 0, 0, 0, 0, 1, 2, 0,
  23.    CUSTOMSCREEN, &myfont, (UBYTE *)"AmigaLIFE -- Radical Eye Software"} ;
  24. /*
  25.  *   Let's use a borderless window too, so we can get vanilla
  26.  *   keys.  This gives us a nicer way to exit and adjust the
  27.  *   speed of the program.  But we still play with the screen
  28.  *   bitmaps.
  29.  */
  30. static struct NewWindow mynewwindow = { 0, 0, 0, 0, 0, 1,
  31.    VANILLAKEY, SIMPLE_REFRESH | ACTIVATE | NOCAREREFRESH | BORDERLESS | BACKDROP,
  32.    NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, CUSTOMSCREEN } ;
  33. /*
  34.  *   This routine gets a raster for temporary storage.
  35.  */
  36. short *myalloc(type)
  37. long type ;
  38. {
  39.    void *AllocMem() ;
  40.    void *p ;
  41.  
  42.    if ((p=AllocMem(2L*RASTSIZE, type | MEMF_CLEAR))==NULL) {
  43.       printf("Could not allocate raster data\n") ;
  44.       cleanup() ;
  45.    }
  46.    return(p) ;
  47. }
  48. /*
  49.  *   Here we set things up.
  50.  */
  51. initialize() {
  52.    long color ;
  53.  
  54.    if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
  55.       "intuition.library",0L))==NULL ||
  56.        (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L))
  57.       ==NULL) {
  58.       printf("Couldn't open libraries.\n") ;
  59.       cleanup() ;
  60.    }
  61.    if ((myscreen = OpenScreen(&mynewscreen))==NULL) {
  62.       printf("Couldn't open screen.\n") ;
  63.       cleanup() ;
  64.    }
  65.    mynewwindow.Screen = myscreen ;
  66.    if ((mywindow = OpenWindow(&mynewwindow))==NULL) {
  67.       printf("Couldn't open window.\n") ;
  68.       cleanup() ;
  69.    }
  70.    a = ((short *)(myscreen->BitMap.Planes[0])) ;
  71.    b = ((short *)(myscreen->BitMap.Planes[1])) ;
  72.    c = ((short *)(myscreen->BitMap.Planes[2])) ;
  73.    d = ((short *)(myscreen->BitMap.Planes[3])) ;
  74.    e = ((short *)(myscreen->BitMap.Planes[4])) ;
  75.    if (asm) {
  76.       t1 = myalloc(0L) ;
  77.       t2 = myalloc(0L) ;
  78.       f = myalloc(0L) ;
  79.    } else {
  80.       t1 = myalloc(MEMF_CHIP) ;
  81.       t2 = myalloc(MEMF_CHIP) ;
  82.       t4 = myalloc(MEMF_CHIP) ;
  83.    }
  84.    t3 = myalloc(MEMF_CHIP) ;
  85.    if (orify) {
  86.       color = GetRGB4(myscreen->ViewPort.ColorMap, 0L) ;
  87.       if (color & 0xf00)
  88.          color -= 256 ;
  89.       if (color & 0xf0)
  90.          color -= 16 ;
  91.       if (color & 0xf)
  92.          color -= 1 ;
  93.       SetRGB4(&(myscreen->ViewPort), 1L << (noplanes - 1), (color >> 8) & 15,
  94.                 (color >> 4) & 15, color & 15) ;
  95.    }
  96.    WaitBlit() ;
  97. }
  98. /*
  99.  *   Exit routine.
  100.  */
  101. cleanup() {
  102.    if (mywindow != NULL)
  103.       CloseWindow(mywindow) ;
  104.    if (myscreen != NULL)
  105.       CloseScreen(myscreen) ;
  106.    if (IntuitionBase)
  107.       CloseLibrary(IntuitionBase) ;
  108.    IntuitionBase = NULL ;
  109.    if (GfxBase)
  110.       CloseLibrary(GfxBase) ;
  111.    GfxBase = NULL ;
  112.    if (t1)
  113.       FreeMem(t1, 2L*RASTSIZE) ;
  114.    if (t2)
  115.       FreeMem(t2, 2L*RASTSIZE) ;
  116.    if (t3)
  117.       FreeMem(t3, 2L*RASTSIZE) ;
  118.    if (t4)
  119.       FreeMem(t4, 2L*RASTSIZE) ;
  120.    if (f)
  121.       FreeMem(f, 2L*RASTSIZE) ;
  122.    exit(0) ;
  123. }
  124. #define PARITY (0x96)
  125. #define CARRY (0xe8)
  126. #define SPEC1 (0x6a)
  127. #define SPEC2 (0xbe)
  128. #define SPEC3 (0x40)
  129. #define COPY (0xf0)
  130. #define ORIFY (0xfc)
  131. #define ORAC (0xfa)
  132. /*
  133.  *   This routine does the necessary four blits to wrap the LIFE image.
  134.  *   Please make sure that you own the blitter when you call it!
  135.  */
  136. struct blitparam blitparam ;
  137. fixit() {
  138.    register struct blitparam *p = &blitparam ;
  139.  
  140.    if (asm) {
  141.       pass3t(f, wmodulo * 2L, (long)vsize) ;
  142.       return ;
  143.    }
  144.    p->bltsize = BLTSIZE(1, vsize) ;
  145.    p->asource = a ;
  146.    p->csource = a + wmodulo - 1 ;
  147.    p->dsource = a + wmodulo - 1 ;
  148.    p->amod = 2 * (wmodulo - 1) ;
  149.    p->bmod = 0 ;
  150.    p->cmod = 2 * (wmodulo - 1) ;
  151.    p->dmod = 2 * (wmodulo - 1) ;
  152.    p->fwm = 0x4000 ;
  153.    p->lwm = 0xffff ;
  154.    p->con0 = SHIFTSHIFT(14) + USEA + USEC + USED + ORAC ;
  155.    p->con1 = 0 ;
  156.    blit(p) ;
  157.    p->asource = a + 2 * wmodulo - 1 ;
  158.    p->csource = a ;
  159.    p->dsource = a ;
  160.    p->fwm = 0x0002 ;
  161.    p->con0 = SHIFTSHIFT(2) + USEA + USEC + USED + ORAC ;
  162.    blit(p) ;
  163.    p->bltsize = BLTSIZE(wmodulo, 1) ;
  164.    p->asource = a + wmodulo ;
  165.    p->dsource = a + wmodulo * (long)(vsize - 1) ;
  166.    p->amod = 0 ;
  167.    p->cmod = 0 ;
  168.    p->dmod = 0 ;
  169.    p->fwm = 0xffff ;
  170.    p->lwm = 0xffff ;
  171.    p->con0 = USEA + USED + COPY ;
  172.    blit(p) ;
  173.    p->asource = a + wmodulo * (long)(vsize - 2) ;
  174.    p->dsource = a ;
  175.    blit(p) ;
  176. }
  177. /*
  178.  *   Does one LIFE generation.  Fancy algorithm uses only 9 blits.  If
  179.  *   anyone can improve this, please let me know.
  180.  */
  181. dogeneration() {
  182.    register struct blitparam *p = &blitparam ;
  183.    register long t ;
  184. /*
  185.  *   Initialize the parameters we are not going to change.
  186.  */
  187.    p->fwm = 0xffff ;
  188.    p->lwm = 0xffff ;
  189.    p->amod = 0 ;
  190.    p->bmod = 0 ;
  191.    p->cmod = 0 ;
  192.    p->dmod = 0 ;
  193.    p->asource = a - wmodulo ;
  194.    p->bsource = a - wmodulo + 1 ;
  195.    p->csource = a - wmodulo ;
  196.    p->dsource = t1 ;
  197.    p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
  198.    p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
  199.    p->con1 = SHIFTSHIFT(15) ;
  200.    if (asm) {
  201.       t = (wmodulo * (long)vsize) >> 1 ;
  202.       pass1(f, t1, t2, t) ;
  203.       pass2(f + wmodulo, t1 + wmodulo, t2 + wmodulo, wmodulo * 2L,
  204.                                                            t - wmodulo) ;
  205.       p->con1 = 0 ;
  206.    } else {
  207.       OwnBlitter() ;
  208.       blit(p) ;
  209.       p->dsource = t2 ;
  210.       p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
  211.       blit(p) ;
  212.       p->csource = t1 + wmodulo ;
  213.       p->dsource = t3 ;
  214.       p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + CARRY ;
  215.       blit(p) ;
  216.       p->bltsize = BLTSIZE(wmodulo, vsize) ;
  217.       p->asource = t2 ;
  218.       p->bsource = t2 + 2 * wmodulo ;
  219.       p->csource = t3 + wmodulo ;
  220.       p->dsource = t4 ;
  221.       p->con1 = 0 ;
  222.       p->con0 = USEA + USEB + USEC + USED + CARRY ;
  223.       blit(p) ;
  224.       p->dsource = t3 ;
  225.       p->con0 = USEA + USEB + USEC + USED + PARITY ;
  226.       blit(p) ;
  227.       p->bltsize = BLTSIZE(wmodulo, vsize+1) ;
  228.       p->asource = a - wmodulo ;
  229.       p->bsource = a - wmodulo + 1 ;
  230.       p->csource = t1 + wmodulo ;
  231.       p->dsource = t2 ;
  232.       p->con0 = SHIFTSHIFT(1) + USEA + USEB + USEC + USED + PARITY ;
  233.       p->con1 = SHIFTSHIFT(15) ;
  234.       blit(p) ;
  235.       p->bltsize = BLTSIZE(wmodulo, vsize) ;
  236.       p->asource = t1 ;
  237.       p->bsource = t2 + wmodulo ;
  238.       p->csource = t3 ;
  239.       p->dsource = t3 ;
  240.       p->con0 = USEA + USEB + USEC + USED + SPEC1 ;
  241.       p->con1 = 0 ;
  242.       blit(p) ;
  243.       p->csource = a ;
  244.       p->dsource = t1 ;
  245.       p->con0 = USEA + USEB + USEC + USED + SPEC2 ;
  246.       blit(p) ;
  247.    }
  248. /*
  249.  *   Before we do the final write, we copy bits down one generation.
  250.  */
  251.    p->bltsize = BLTSIZE(wmodulo, vsize) ;
  252.    if (noplanes > 1 && asm)
  253.       OwnBlitter() ;
  254.    if (orify) {
  255.       a = ((short *)(myscreen->BitMap.Planes[0])) ;
  256.       p->asource = 
  257.          ((short *)(myscreen->BitMap.Planes[noplanes-1])) ;
  258.       p->bsource = 
  259.          ((short *)(myscreen->BitMap.Planes[noplanes-2])) ;
  260.       p->dsource = p->asource ;
  261.       p->con0 = USEA + USEB + USED + ORIFY ;
  262.       blit(p) ;
  263.    }
  264.    p->con0 = USEA + USED + COPY ;
  265.    switch (noplanes - orify) {
  266. case 5:
  267.    p->asource = d ;
  268.    p->dsource = e ;
  269.    blit(p) ;
  270. case 4:
  271.    p->asource = c ;
  272.    p->dsource = d ;
  273.    blit(p) ;
  274. case 3:
  275.    p->asource = b ;
  276.    p->dsource = c ;
  277.    blit(p) ;
  278. case 2:
  279.    p->asource = a ;
  280.    p->dsource = b ;
  281.    blit(p) ;
  282. default: ;
  283.    }
  284.    if (! asm) {
  285.       p->bltsize = BLTSIZE(wmodulo, vsize-2) ;
  286.       p->asource = t1 + wmodulo ;
  287.       p->bsource = t3 + wmodulo ;
  288.       p->csource = t4 + wmodulo ;
  289.       p->dsource = a + wmodulo ;
  290.       p->fwm = 0x7fff ;
  291.       p->lwm = 0xfffe ;
  292.       p->con0 = USEA + USEB + USEC + USED + SPEC3 ;
  293.       blit(p) ;
  294.    } else {
  295.       CopyMemQuick(f, a, msize) ;
  296.    }
  297. /*
  298.  *   Wrap, if necessary
  299.  */
  300.    if (torus)
  301.       fixit() ;
  302.    else if (asm) {
  303.       pass3(f, wmodulo * 2L, (long)vsize) ;
  304.    }
  305.    if (! asm || noplanes > 1)
  306.       DisownBlitter() ;
  307. }
  308. /*
  309.  *   Random number generator; probably not a very good one.
  310.  */
  311. int rnd(i)
  312. int i ;
  313. {
  314.    static long seed = 323214521 ;
  315.    long rval ;
  316.  
  317.    seed = seed * 123213 + 121 ;
  318.    rval = (seed >> 5) & 65535 ;
  319.    return ((i * rval) >> 16) ;
  320. }
  321. /*
  322.  *   Main routine.  If called with no arguments, makes 1 bit plane screen.
  323.  *   Otherwise, first argument is used as the number of bit planes.
  324.  */
  325. char buffer[200] ;
  326. long time1[3], time2[3] ;
  327. long ratio(a,b,c)
  328. register long a, b, c ;
  329. {
  330.    while (a > 32768L) {
  331.       a /= 2 ;
  332.       c /= 2 ;
  333.    }
  334.    while (b > 32768L) {
  335.       b /= 2 ;
  336.       c /= 2 ;
  337.    }
  338.    if (c == 0)
  339.       return(0) ;
  340.    else
  341.       return(a * b / c) ;
  342. }
  343. count(a, h, v)
  344. register long *a ;
  345. long h, v ;
  346. {
  347.    register long s, i ;
  348.    h = v * (h >> 5) ;
  349.    s = 0 ;
  350.    for (i=0; i<h; i++)
  351.       if (*a++ == 0)
  352.          s ++ ;
  353.    printf("%ld/%ld\n", s, h) ;
  354. }
  355. main (argc, argv)
  356. int argc ;
  357. char *argv[] ;
  358. {
  359.    register int x, y ;
  360.    int hires = 320 ;
  361.    int randoms = 0 ;
  362.    int ir ;
  363.    int dvsize = 0 ;
  364.    struct IntuiMessage *message ;
  365.    int code ;
  366.    long delayval = 0 ;
  367.    long generations ;
  368.    long t ;
  369.    short *wh ;
  370.  
  371.    printf("LIFE 5.0, Copyright 1990 Radical Eye Software\n") ;
  372.    noplanes = 1 ;
  373.    while (argc > 1 && argv[1][0]=='-') {
  374.       argc-- ;
  375.       argv++ ;
  376.       if (argv[0][1]=='h' || argv[0][1]=='H') {
  377.          if (sscanf(argv[0]+2, "%d", &hires)!=1)
  378.             hires = 640 ;
  379.       } else if (argv[0][1]=='a' || argv[0][1]=='A') {
  380.          asm = 1 ;
  381.       } else if (argv[0][1]=='r' || argv[0][1]=='R') {
  382.          if (sscanf(argv[0]+2, "%d", &randoms)!=1)
  383.             randoms = 1 ;
  384.       } else if (argv[0][1]=='p' || argv[0][1]=='P') {
  385.          noplanes = argv[0][2] - '0' ;
  386.          if (noplanes < 1 || noplanes > 6)
  387.             noplanes = 1 ;
  388.       } else if (argv[0][1]=='o' || argv[0][1]=='O') {
  389.          orify = 1 ;
  390.       } else if (argv[0][1]=='t' || argv[0][1]=='T') {
  391.          torus = 1 ;
  392.       } else if (argv[0][1]=='v' || argv[0][1]=='V') {
  393.          if (sscanf(argv[0]+2, "%d", &dvsize)!=1)
  394.             dvsize = 0 ;
  395.       } else if (argv[0][1]=='s' || argv[0][1]=='S') {
  396.          delayval = -1 ;
  397.       }
  398.    }
  399.    if (noplanes == 1)
  400.       orify = 0 ;
  401.    if (argc > 1) {
  402.       if (argv[1][0]=='?' && argv[1][1]==0) {
  403.          printf(
  404.    "Usage:  life [-h[n]] [-r[n]] [-p[n]] [-o] [-t] [-v[n]] [-s] [infile]\n") ;
  405.          cleanup() ;
  406.       }
  407.       if (freopen(argv[1], "r", stdin)==NULL) {
  408.          printf("Couldn't open %s\n", argv[1]) ;
  409.          cleanup() ;
  410.       }
  411.    }
  412.    if (hires > 400) {
  413.       vsize = 400 ;
  414.       mynewscreen.ViewModes |= HIRES ;
  415.    } else {
  416.       vsize = 200 ;
  417.    }
  418.    modulo = hires & ~31 ;
  419.    hires = modulo ;
  420.    ir = randoms ;
  421.    if (dvsize >= 10 && dvsize <= 600)
  422.       vsize = dvsize ;
  423.    wmodulo = modulo / 16 ;
  424.    mynewscreen.Depth = noplanes ;
  425.    mynewscreen.Width = modulo ;
  426.    mynewscreen.Height = vsize ;
  427.    mynewwindow.Width = modulo ;
  428.    mynewwindow.Height = vsize ;
  429.    msize = wmodulo * (long)vsize * 2 ;
  430.    if (vsize > 300)
  431.       mynewscreen.ViewModes |= LACE ;
  432.    initialize() ;
  433.    SetAPen(&myscreen->RastPort, 0L) ;
  434.    RectFill(&myscreen->RastPort, 0L, 0L, (long)hires-1, (long)vsize-1) ;
  435.    WaitBlit() ;
  436.    if (asm) {
  437.       wh = f ;
  438.       CopyMemQuick(a, f, msize) ;
  439.    } else
  440.       wh = a ;
  441.    readin(wh) ;
  442.    if (torus) {
  443.       OwnBlitter() ;
  444.       fixit() ;
  445.       DisownBlitter() ;
  446.    }
  447.    WaitBlit() ;
  448.    generations = 0 ;
  449.    DateStamp(time1) ;
  450.    while (1) {
  451.       if (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
  452.          code = message->Code ;
  453.          ReplyMsg(message) ;
  454.          switch(code) {
  455. case 27 : case 3 : case 'q' : case 'Q' : case 'x' : case 'X' :
  456.             goto done ;
  457. case 'c' : case 'C' :
  458.             count(a, (long)hires, (long)vsize) ;
  459.             break ;
  460. case '0' : case 'g' : case 'G' :
  461.             delayval = 0 ;
  462.             break ;
  463. case '1' : case '2' : case '3' : case '4' :
  464. case '5' : case '6' : case '7' : case '8' : case '9' :
  465.             delayval = 1L << (code - '0') ;
  466.             break ;
  467. case ' ' :
  468.             delayval = -1 ;
  469.             goto doone ;
  470. case 'S' : case 's' :
  471.             delayval = -1 ;
  472. default :
  473.             break ;
  474.          }
  475.       }
  476.       if (delayval) {
  477.          if (delayval == -1)
  478.             continue ;
  479.          Delay(delayval) ;
  480.       }
  481. doone:
  482.       if (randoms) {
  483.          if (ir-- == 0) {
  484.             x = rnd(modulo-2) + 1 ;
  485.             y = rnd(vsize-2) + 1 ;
  486.             if (!asm || noplanes > 1)
  487.                WaitBlit() ;
  488.             wh[y * (long)wmodulo + (x >> 4)] |= 1 << (15 - (15 & x)) ;
  489.             ir = randoms ;
  490.          }
  491.       }
  492.       dogeneration() ;
  493.       generations++ ;
  494.    }
  495. done:
  496.    DateStamp(time2) ;
  497.    delayval = time2[2]-time1[2] + (time2[1]-time1[1]) * 3000L
  498.               + (time2[0]-time1[0]) * 4320000L ;
  499.    t = (modulo - 2) * (long)(vsize - 2) * 50L ;
  500.    t = ((t / delayval) * generations +
  501.         ratio(t % delayval, generations, delayval)) ;
  502.    printf("%ld generations by %ld pixels in %ld ticks is %ld cells/sec\n",
  503.            generations, (modulo-2)*(long)(vsize-2), delayval, t) ;
  504.    cleanup() ;
  505. }
  506.